package com.elitedatai.mchtest.flyer.service.impl;

import com.elitedatai.mchtest.flyer.model.dto.FlyerDTO;
import com.elitedatai.mchtest.flyer.model.entity.Flyer;
import com.elitedatai.mchtest.flyer.repository.FlyerRepository;
import com.elitedatai.mchtest.flyer.service.IFlyerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 飞手服务实现类
 * 
 * 该类实现了IFlyerService接口，提供飞手管理的完整业务功能，包括：
 * - 飞手的增删改查操作
 * - 飞手状态管理
 * - 飞行数据统计更新
 * - 安全评级计算
 * - 数据验证和业务规则处理
 * 
 * 主要功能模块：
 * 1. 基础CRUD操作（创建、查询、更新、删除）
 * 2. 条件查询和分页查询
 * 3. 飞行数据统计（飞行时长、任务次数、事故次数等）
 * 4. 安全评级自动计算和更新
 * 5. 数据唯一性验证（飞手ID、电话、邮箱）
 * 6. 批量操作支持
 * 
 * @author 系统生成
 * @version 1.0
 * @since 2024
 */
@Slf4j
@Service
@Transactional
public class FlyerServiceImpl implements IFlyerService {

    /**
     * 飞手数据访问层，用于数据库操作
     */
    @Autowired
    private FlyerRepository flyerRepository;

    @Override
    public FlyerDTO createFlyer(FlyerDTO flyerDTO) {
        log.info("创建飞手: {}", flyerDTO.getFlyerId());
        
        // 将DTO转换为实体
        Flyer flyer = convertToEntity(flyerDTO);
        
        // 验证必填字段
        validateRequiredFields(flyer);
        
        // 验证数据唯一性
        validateUniqueFields(flyer, null);
        
        // 初始化默认值
        initializeDefaultValues(flyer);
        
        // 计算初始安全评级
        calculateSafetyRating(flyer);
        
        Flyer savedFlyer = flyerRepository.save(flyer);
        log.info("飞手创建成功: {}", savedFlyer.getFlyerId());
        return convertToDTO(savedFlyer);
    }

    @Override
    public Optional<FlyerDTO> updateFlyerById(Long id, FlyerDTO flyerDTO) {
        log.info("更新飞手信息: ID={}", id);
        
        return flyerRepository.findById(id).map(existingFlyer -> {
            // 将DTO转换为实体
            Flyer flyer = convertToEntity(flyerDTO);
            
            // 验证数据唯一性（排除当前记录）
            validateUniqueFields(flyer, existingFlyer.getFlyerId());
            
            // 更新字段
            updateFlyerFields(existingFlyer, flyer);
            
            // 重新计算安全评级
            calculateSafetyRating(existingFlyer);
            
            Flyer updatedFlyer = flyerRepository.save(existingFlyer);
            log.info("飞手信息更新成功: {}", updatedFlyer.getFlyerId());
            return convertToDTO(updatedFlyer);
        });
    }

    @Override
    public Optional<FlyerDTO> updateFlyerByFlyerId(String flyerId, FlyerDTO flyerDTO) {
        log.info("根据飞手ID更新飞手信息: {}", flyerId);
        
        return flyerRepository.findByFlyerId(flyerId).map(existingFlyer -> {
            // 将DTO转换为实体
            Flyer flyer = convertToEntity(flyerDTO);
            
            // 验证数据唯一性（排除当前记录）
            validateUniqueFields(flyer, flyerId);
            
            // 更新字段
            updateFlyerFields(existingFlyer, flyer);
            
            // 重新计算安全评级
            calculateSafetyRating(existingFlyer);
            
            Flyer updatedFlyer = flyerRepository.save(existingFlyer);
            log.info("飞手信息更新成功: {}", updatedFlyer.getFlyerId());
            return convertToDTO(updatedFlyer);
        });
    }

    @Override
    public boolean deleteFlyerById(Long id) {
        log.info("删除飞手: ID={}", id);
        
        if (flyerRepository.existsById(id)) {
            flyerRepository.deleteById(id);
            log.info("飞手删除成功: ID={}", id);
            return true;
        }
        
        log.warn("飞手不存在: ID={}", id);
        return false;
    }

    @Override
    public boolean deleteFlyerByFlyerId(String flyerId) {
        log.info("根据飞手ID删除飞手: {}", flyerId);
        
        if (flyerRepository.existsByFlyerId(flyerId)) {
            flyerRepository.deleteByFlyerId(flyerId);
            log.info("飞手删除成功: {}", flyerId);
            return true;
        }
        
        log.warn("飞手不存在: {}", flyerId);
        return false;
    }

    @Override
    public Optional<FlyerDTO> getFlyerById(Long id) {
        log.debug("根据ID查询飞手: {}", id);
        return flyerRepository.findById(id).map(this::convertToDTO);
    }

    @Override
    public Optional<FlyerDTO> getFlyerByFlyerId(String flyerId) {
        log.debug("根据飞手ID查询飞手: {}", flyerId);
        return flyerRepository.findByFlyerId(flyerId).map(this::convertToDTO);
    }

    @Override
    public List<FlyerDTO> getFlyersByName(String flyerName) {
        log.debug("根据姓名查询飞手: {}", flyerName);
        return flyerRepository.findByFlyerName(flyerName).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<FlyerDTO> getFlyersByStatus(Integer status) {
        log.debug("根据状态查询飞手: {}", status);
        return flyerRepository.findByStatus(status).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<FlyerDTO> getFlyersByQualificationType(String qualificationType) {
        log.debug("根据资质类型查询飞手: {}", qualificationType);
        return flyerRepository.findByQualificationType(qualificationType).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<FlyerDTO> getFlyersByCertificationLevel(String certificationLevel) {
        log.debug("根据认证等级查询飞手: {}", certificationLevel);
        return flyerRepository.findByCertificationLevel(certificationLevel).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<FlyerDTO> getAllFlyers() {
        log.debug("查询所有飞手");
        return flyerRepository.findAll().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public Page<FlyerDTO> getAllFlyers(Pageable pageable) {
        log.debug("分页查询所有飞手: page={}, size={}", pageable.getPageNumber(), pageable.getPageSize());
        return flyerRepository.findAllOrderByCreateTimeDesc(pageable)
                .map(this::convertToDTO);
    }

    @Override
    public Page<FlyerDTO> getFlyersByStatus(Integer status, Pageable pageable) {
        log.debug("根据状态分页查询飞手: status={}, page={}, size={}", 
                 status, pageable.getPageNumber(), pageable.getPageSize());
        return flyerRepository.findByStatusOrderByCreateTimeDesc(status, pageable)
                .map(this::convertToDTO);
    }

    @Override
    public List<FlyerDTO> getFlyersByMultipleConditions(String flyerId, String flyerName, Integer status, 
                                                       String qualificationType, String certificationLevel) {
        log.debug("多条件查询飞手: flyerId={}, flyerName={}, status={}, qualificationType={}, certificationLevel={}", 
                 flyerId, flyerName, status, qualificationType, certificationLevel);
        return flyerRepository.findFlyersByMultipleConditions(flyerId, flyerName, status, qualificationType, certificationLevel)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean existsByFlyerId(String flyerId) {
        return flyerRepository.existsByFlyerId(flyerId);
    }

    @Override
    public boolean existsByPhone(String phone) {
        return flyerRepository.existsByPhone(phone);
    }

    @Override
    public boolean existsByEmail(String email) {
        return flyerRepository.existsByEmail(email);
    }

    @Override
    public boolean updateFlyerStatus(String flyerId, Integer status) {
        log.info("更新飞手状态: flyerId={}, status={}", flyerId, status);
        
        return flyerRepository.findByFlyerId(flyerId).map(flyer -> {
            flyer.setStatus(status);
            flyerRepository.save(flyer);
            log.info("飞手状态更新成功: flyerId={}, status={}", flyerId, status);
            return true;
        }).orElse(false);
    }

    @Override
    public boolean addFlightHours(String flyerId, BigDecimal additionalHours) {
        log.info("增加飞行时长: flyerId={}, additionalHours={}", flyerId, additionalHours);
        
        if (additionalHours == null || additionalHours.compareTo(BigDecimal.ZERO) <= 0) {
            log.warn("飞行时长增量无效: {}", additionalHours);
            return false;
        }
        
        return flyerRepository.findByFlyerId(flyerId).map(flyer -> {
            BigDecimal currentHours = flyer.getTotalFlightHours() != null ? flyer.getTotalFlightHours() : BigDecimal.ZERO;
            flyer.setTotalFlightHours(currentHours.add(additionalHours));
            flyerRepository.save(flyer);
            log.info("飞行时长更新成功: flyerId={}, totalHours={}", flyerId, flyer.getTotalFlightHours());
            return true;
        }).orElse(false);
    }

    @Override
    public boolean addMissions(String flyerId, Integer additionalMissions) {
        log.info("增加飞手任务次数: flyerId={}, additionalMissions={}", flyerId, additionalMissions);
        
        Optional<Flyer> flyerOpt = flyerRepository.findByFlyerId(flyerId);
        if (flyerOpt.isPresent()) {
            Flyer flyer = flyerOpt.get();
            Integer currentMissions = flyer.getTotalMissions() != null ? flyer.getTotalMissions() : 0;
            flyer.setTotalMissions(currentMissions + additionalMissions);
            flyer.setUpdateTime(System.currentTimeMillis());
            
            // 重新计算安全评级
            calculateSafetyRating(flyer);
            
            flyerRepository.save(flyer);
            log.info("飞手任务次数更新成功: flyerId={}, newTotal={}", flyerId, flyer.getTotalMissions());
            return true;
        }
        
        log.warn("飞手不存在: {}", flyerId);
        return false;
    }

    @Override
    public boolean addAccidents(String flyerId, Integer additionalAccidents) {
        log.info("增加飞手事故次数: flyerId={}, additionalAccidents={}", flyerId, additionalAccidents);
        
        Optional<Flyer> flyerOpt = flyerRepository.findByFlyerId(flyerId);
        if (flyerOpt.isPresent()) {
            Flyer flyer = flyerOpt.get();
            Integer currentAccidents = flyer.getAccidentCount() != null ? flyer.getAccidentCount() : 0;
            flyer.setAccidentCount(currentAccidents + additionalAccidents);
            flyer.setUpdateTime(System.currentTimeMillis());
            
            // 重新计算安全评级
            calculateSafetyRating(flyer);
            
            flyerRepository.save(flyer);
            log.info("飞手事故次数更新成功: flyerId={}, newTotal={}", flyerId, flyer.getAccidentCount());
            return true;
        }
        
        log.warn("飞手不存在: {}", flyerId);
        return false;
    }

    @Override
    public boolean addViolations(String flyerId, Integer additionalViolations) {
        log.info("增加飞手违规次数: flyerId={}, additionalViolations={}", flyerId, additionalViolations);
        
        Optional<Flyer> flyerOpt = flyerRepository.findByFlyerId(flyerId);
        if (flyerOpt.isPresent()) {
            Flyer flyer = flyerOpt.get();
            Integer currentViolations = flyer.getViolationCount() != null ? flyer.getViolationCount() : 0;
            flyer.setViolationCount(currentViolations + additionalViolations);
            flyer.setUpdateTime(System.currentTimeMillis());
            flyerRepository.save(flyer);
            log.info("飞手违规次数更新成功: flyerId={}, newTotal={}", flyerId, flyer.getViolationCount());
            return true;
        }
        
        log.warn("飞手不存在: {}", flyerId);
        return false;
    }

    @Override
    public boolean calculateAndUpdateSafetyRating(String flyerId) {
        log.info("计算并更新飞手安全评级: {}", flyerId);
        
        Optional<Flyer> flyerOpt = flyerRepository.findByFlyerId(flyerId);
        if (flyerOpt.isPresent()) {
            Flyer flyer = flyerOpt.get();
            calculateSafetyRating(flyer);
            flyer.setUpdateTime(System.currentTimeMillis());
            flyerRepository.save(flyer);
            log.info("飞手安全评级更新成功: flyerId={}, safetyRating={}", flyerId, flyer.getSafetyRating());
            return true;
        }
        
        log.warn("飞手不存在: {}", flyerId);
        return false;
    }

    @Override
    public int batchUpdateFlyerStatus(List<String> flyerIds, Integer status) {
        log.info("批量更新飞手状态: flyerIds={}, status={}", flyerIds, status);
        
        int updateCount = 0;
        for (String flyerId : flyerIds) {
            if (updateFlyerStatus(flyerId, status)) {
                updateCount++;
            }
        }
        
        log.info("批量更新完成: 成功更新{}个飞手状态", updateCount);
        return updateCount;
    }

    /**
     * 验证必填字段
     */
    private void validateRequiredFields(Flyer flyer) {
        if (!StringUtils.hasText(flyer.getFlyerId())) {
            throw new IllegalArgumentException("飞手ID不能为空");
        }
        if (!StringUtils.hasText(flyer.getFlyerName())) {
            throw new IllegalArgumentException("飞手姓名不能为空");
        }
    }

    /**
     * 验证数据唯一性
     */
    private void validateUniqueFields(Flyer flyer, String excludeFlyerId) {
        // 验证飞手ID唯一性
        if (StringUtils.hasText(flyer.getFlyerId()) && 
            !flyer.getFlyerId().equals(excludeFlyerId) && 
            flyerRepository.existsByFlyerId(flyer.getFlyerId())) {
            throw new IllegalArgumentException("飞手ID已存在: " + flyer.getFlyerId());
        }
        
        // 验证电话号码唯一性
        if (StringUtils.hasText(flyer.getPhone())) {
            flyerRepository.findByPhone(flyer.getPhone()).ifPresent(existingFlyer -> {
                if (!existingFlyer.getFlyerId().equals(excludeFlyerId)) {
                    throw new IllegalArgumentException("电话号码已存在: " + flyer.getPhone());
                }
            });
        }
        
        // 验证邮箱唯一性
        if (StringUtils.hasText(flyer.getEmail())) {
            flyerRepository.findByEmail(flyer.getEmail()).ifPresent(existingFlyer -> {
                if (!existingFlyer.getFlyerId().equals(excludeFlyerId)) {
                    throw new IllegalArgumentException("邮箱已存在: " + flyer.getEmail());
                }
            });
        }
    }

    /**
     * 初始化默认值
     */
    private void initializeDefaultValues(Flyer flyer) {
        if (flyer.getTotalFlightHours() == null) {
            flyer.setTotalFlightHours(BigDecimal.ZERO);
        }
        if (flyer.getTotalMissions() == null) {
            flyer.setTotalMissions(0);
        }
        if (flyer.getAccidentCount() == null) {
            flyer.setAccidentCount(0);
        }
        if (flyer.getViolationCount() == null) {
            flyer.setViolationCount(0);
        }
    }

    /**
     * 更新飞手字段
     */
    private void updateFlyerFields(Flyer existingFlyer, Flyer newFlyer) {
        if (StringUtils.hasText(newFlyer.getFlyerName())) {
            existingFlyer.setFlyerName(newFlyer.getFlyerName());
        }
        if (StringUtils.hasText(newFlyer.getPhone())) {
            existingFlyer.setPhone(newFlyer.getPhone());
        }
        if (StringUtils.hasText(newFlyer.getEmail())) {
            existingFlyer.setEmail(newFlyer.getEmail());
        }
        if (newFlyer.getStatus() != null) {
            existingFlyer.setStatus(newFlyer.getStatus());
        }
        if (StringUtils.hasText(newFlyer.getQualificationType())) {
            existingFlyer.setQualificationType(newFlyer.getQualificationType());
        }
        if (StringUtils.hasText(newFlyer.getCertificateNumber())) {
            existingFlyer.setCertificateNumber(newFlyer.getCertificateNumber());
        }
        if (newFlyer.getQualificationExpiry() != null) {
            existingFlyer.setQualificationExpiry(newFlyer.getQualificationExpiry());
        }
        if (StringUtils.hasText(newFlyer.getCertificationLevel())) {
            existingFlyer.setCertificationLevel(newFlyer.getCertificationLevel());
        }
        if (newFlyer.getTotalFlightHours() != null) {
            existingFlyer.setTotalFlightHours(newFlyer.getTotalFlightHours());
        }
        if (newFlyer.getTotalMissions() != null) {
            existingFlyer.setTotalMissions(newFlyer.getTotalMissions());
        }
        if (newFlyer.getAccidentCount() != null) {
            existingFlyer.setAccidentCount(newFlyer.getAccidentCount());
        }
        if (newFlyer.getViolationCount() != null) {
            existingFlyer.setViolationCount(newFlyer.getViolationCount());
        }
    }

    /**
     * 计算安全评级
     * 根据事故次数占累计任务次数的比例计算安全评级
     * 比例每满20%扣一分，满分5分，不满一分的再次按比例扣，可包含两位小数
     */
    private void calculateSafetyRating(Flyer flyer) {
        Integer totalMissions = flyer.getTotalMissions() != null ? flyer.getTotalMissions() : 0;
        Integer accidentCount = flyer.getAccidentCount() != null ? flyer.getAccidentCount() : 0;
        
        if (totalMissions == 0) {
            // 如果没有任务记录，默认满分
            flyer.setSafetyRating(new BigDecimal("5.00"));
            return;
        }
        
        // 计算事故比例
        BigDecimal accidentRatio = new BigDecimal(accidentCount)
                .divide(new BigDecimal(totalMissions), 4, RoundingMode.HALF_UP);
        
        // 满分5分
        BigDecimal maxRating = new BigDecimal("5.00");
        
        // 每20%扣1分，不满20%的部分按比例扣分
        BigDecimal deductionRatio = new BigDecimal("0.20"); // 20%
        BigDecimal deductionPerUnit = BigDecimal.ONE; // 每20%扣1分
        
        // 计算扣分
        BigDecimal deduction = accidentRatio.divide(deductionRatio, 4, RoundingMode.HALF_UP)
                .multiply(deductionPerUnit);
        
        // 计算最终评级
        BigDecimal safetyRating = maxRating.subtract(deduction);
        
        // 确保评级不低于0
        if (safetyRating.compareTo(BigDecimal.ZERO) < 0) {
            safetyRating = BigDecimal.ZERO;
        }
        
        // 保留两位小数
        flyer.setSafetyRating(safetyRating.setScale(2, RoundingMode.HALF_UP));
    }

    /**
     * 将实体转换为DTO
     */
    private FlyerDTO convertToDTO(Flyer flyer) {
        FlyerDTO flyerDTO = new FlyerDTO();
        BeanUtils.copyProperties(flyer, flyerDTO);
        return flyerDTO;
    }

    /**
     * 将DTO转换为实体
     */
    private Flyer convertToEntity(FlyerDTO flyerDTO) {
        Flyer flyer = new Flyer();
        BeanUtils.copyProperties(flyerDTO, flyer);
        return flyer;
    }
}